home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 297_01 / prscan.c < prev    next >
C/C++ Source or Header  |  1980-01-01  |  10KB  |  520 lines

  1. /* prscan.c */
  2. /* lexical analysis */
  3. #include <stdio.h>
  4. #include <ctype.h>
  5.  
  6. #include "prtypes.h"
  7. #include "prlex.h"
  8.  
  9. #define EOFINCOMMENT "End of file in comment "
  10. #define EOFINCHAR "End of file in char"
  11.  
  12. extern char *Read_buffer;
  13. extern char *Print_buffer;
  14. extern int Max_Readbuffer;
  15.  
  16. #if LOGGING_CAPABILITY
  17. extern FILE *Log_file;
  18. int Unget_flag = 0;
  19. #endif
  20.  
  21. FILE *Curr_infile; /* initialised in pralloc.c */
  22.  
  23. static char *Rbuffptr;
  24. CHAR Ch = '\0';
  25. static void scan_identifier(), scan_string();
  26. static int scan_number();
  27.  
  28.  
  29. #ifdef CHARACTER
  30. CHAR Char_scanned;
  31. static int scan_character();
  32. #endif
  33.  
  34. #if STRING_READ_CAPABILITY
  35. /* the following two variables let you read from a string */
  36.  
  37. char *Curr_string_input;   /* this is where we would get the next char */
  38. int String_input_flag = 0; /* if this is 0 then read from a file */
  39.  
  40. #endif
  41.  
  42. /* Character types - see prlex.h.
  43.  * There is a bit of guess work once we go past 127 
  44.  */
  45. int Ctype[256] = {
  46.     CC, CC, CC, CC, CC, CC, CC, CC, CC, SP,  /* O - 9 */
  47.     SP, CC, CC, SP, CC, CC, CC, CC, CC, CC,  /* 10 - 19 */
  48.     CC, CC, CC, CC, CC, OT, OT, OT, OT, OT,  /* 20 - 29 */
  49.     OT, OT, SP, OT, QU, OT, OT, OT, OT, AP,  /* 30 - 39 */
  50.     BR, BR, OT, SI, OT, SI, OT, OT, DI, DI,  /* 40 - 49 */
  51.     DI, DI, DI, DI, DI, DI, DI, DI, OT, OT,  /* 50 - 59 */
  52.     OT, OT, OT, QE, OT, AU, AU, AU, AU, AU,  /* 60 - 69 */
  53.     AU, AU, AU, AU, AU, AU, AU, AU, AU, AU,  /* 70 - 79 */
  54.     AU, AU, AU, AU, AU, AU, AU, AU, AU, AU,  /* 80 - 89 */
  55.     AU, OT, OT, OT, OT, US, OT, AL, AL, AL,  /* 90 - 99 */
  56.     AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,  /* 100 - 109 */
  57.     AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,  /* 110 - 119 */
  58.     AL, AL, AL, OT, BA, OT, OT, OT, OT, OT,  /* 120 - 129 */
  59.     AL, AL, AL, AL, AL, AL, AL, AL, AL, AL,  /* 130 - 139 */
  60.     AL, AL, AU, AU, AU, AL, OT, AL, AL, AL,  /* 140 - 149 */
  61.     AL, AL, AL, AU, AU, OT, OT, OT, OT, OT,  /* 150 - 159 */
  62.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 160 - 169 */
  63.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 170 - 179 */
  64.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 180 - 189 */
  65.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 190 - 199 */
  66.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 200 - 209 */
  67.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 210 - 219 */
  68.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 220 - 229 */
  69.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 230 - 240 */
  70.     OT, OT, OT, OT, OT, OT, OT, OT, OT, OT,  /* 240 - 249 */
  71.     OT, OT, OT, OT, OT, OT
  72. };
  73.  
  74. /******************************************************************
  75.             ini_scan()
  76. Called by scan().
  77. *******************************************************************/
  78. static void ini_scan()
  79. {
  80.  
  81.     lookahead();/* move to next non blank */
  82.     Rbuffptr = Read_buffer;
  83. }
  84.  
  85.  
  86. /****************************************************************
  87.         get_nc_char
  88. get non commented character
  89. get next char out of comments and not in string
  90. *****************************************************************/
  91. get_nc_char()
  92. {
  93.     CHAR c;
  94.     static prevc = ' ';
  95.     static inside_comment=0;
  96.  
  97.     for(;;){
  98.         c =  getc(Curr_infile);
  99.         if(inside_comment)
  100.         {
  101.             if(prevc == '*' && c == '/')
  102.             {
  103.                 inside_comment = 0;
  104.                 prevc = ' ';
  105.                 continue;
  106.             }
  107.             if(c == '\n' || c == '\r')
  108.             {
  109.                 return(c);
  110.             }
  111.             if(c == '*')
  112.             {
  113.                 c =  getc(Curr_infile);
  114.                 if(c == '/')
  115.                 {
  116.                     inside_comment = 0;
  117.                 }
  118.                 prevc = c;
  119.                 continue;
  120.             }
  121.             else
  122.                 if(c == EOF)
  123.                 {
  124.                     fatal(EOFINCOMMENT);
  125.                     return(EOF);
  126.                 }
  127.             prevc = c;
  128.             continue;
  129.         }
  130.         else    if/* not inside comments */
  131.         (c == '/')
  132.         {
  133.             c =  getc(Curr_infile);
  134.             if( c == '*')
  135.             {
  136.                 inside_comment = 1;
  137.                 continue;
  138.             }
  139.             else
  140.             {
  141.                 ungetc(c, Curr_infile);
  142.                 return((short)'/');
  143.             }
  144.         }
  145.         else
  146.             if(c == EOF)
  147.                 return(EOF);
  148.             else
  149.                 if(c ==  '\n')
  150.                 {
  151.                     return(c);
  152.                 }
  153.         return(c);
  154.     }
  155. }
  156.  
  157.  
  158. /******************************************************************
  159.             getachar()
  160. The only routine you should use for reading a char.
  161. *******************************************************************/
  162.  
  163. /* too crude */
  164. CHAR getachar()
  165. {
  166.     extern unsigned int Inp_linecount;
  167. #if STRING_READ_CAPABILITY
  168.     if(String_input_flag)
  169.     {
  170.         Ch = *Curr_string_input++;
  171.         if(Ch == '\0')
  172.         {
  173.             Curr_string_input--;
  174.             Ch = EOF;
  175.         }
  176.     }
  177.     else
  178. #endif
  179.         Ch = get_nc_char();
  180.  
  181.     if(Ch == '\n')
  182.         Inp_linecount ++;
  183. #if LOGGING_CAPABILITY /* new version */
  184.  
  185.     if(Ch != '\0' && Log_file != NULL && !Unget_flag)
  186.       {
  187.       fprintf( Log_file,"%c", Ch);
  188.       }
  189.     Unget_flag = 0;
  190. #endif
  191.     return(Ch);
  192. }
  193.  
  194. /******************************************************************
  195.             ungetachar()
  196. Put just one char back on input stream.
  197. Cannot be used without a prior call to getachar().
  198. *******************************************************************/
  199.  
  200. ungetachar()
  201. {
  202. #if STRING_READ_CAPABILITY
  203.     if(String_input_flag)
  204.         Curr_string_input--;
  205.     else
  206. #endif
  207.         ungetc(Ch, Curr_infile);
  208. Unget_flag = 1;
  209. }
  210. /******************************************************************
  211.             lookahead()
  212.  Peek at next character, 
  213.  but this character can be read by getachar()
  214.  ******************************************************************/
  215. CHAR lookahead()
  216. {
  217.     do{
  218.         getachar();
  219.     }  while(isspace(Ch));
  220.  
  221.     ungetachar();
  222.     return(Ch);
  223. }
  224.  
  225.  
  226.  
  227. /******************************************************************
  228.             scan()
  229. See prlex.h for return values other than characters (i.e. > 256)
  230. *******************************************************************/
  231. int scan()
  232. {
  233.     ini_scan();
  234.     getachar();
  235.     if(Ch == EOF)
  236.         return(EOF);
  237.     switch(Ctype[Ch])
  238.     {
  239.  
  240.     case DI:
  241.         MY_ASSERT(isdigit(Ch)); /* double check */
  242.     case SI:
  243.         MY_ASSERT(isdigit(Ch) || Ch == '-' || Ch == '+');
  244.         return(scan_number(Ch));
  245.  
  246.     case QU:
  247.         MY_ASSERT(Ch == '"');
  248.         scan_string();
  249.         return(TOKEN_STRING);
  250.  
  251.     case BR:
  252.         MY_ASSERT(Ch == ')' || Ch == '(');
  253.         return(Ch);
  254.  
  255. #ifdef CLIPS_SYNTAX
  256.     case QE:
  257.         scan_identifier(?);
  258.         return(TOKEN_VAR);
  259.     case AL:
  260.     case AU:
  261.     case OT:
  262.         scan_identifier(Ch);
  263.         return(TOKEN_ATOM);
  264. #else
  265.     case AL:
  266.         MY_ASSERT(islower(Ch));
  267.         scan_identifier(Ch);
  268.         return(TOKEN_ATOM);
  269.  
  270.     case US:
  271.         MY_ASSERT(Ch == '_');
  272.  
  273.     case AU:
  274.         scan_identifier(Ch);
  275.         return(TOKEN_VAR);
  276. #endif
  277.     case CC:
  278.         return(SCAN_ERR);
  279. #ifdef  CHARACTER
  280.     case AP:
  281.         return(scan_character());
  282. #endif
  283.     default:
  284.         return(Ch);
  285.     }
  286. }
  287.  
  288. /******************************************************************
  289.             scan_identifier()
  290. Read an identifier.
  291. ******************************************************************/
  292. static void  scan_identifier(c)
  293. int c;
  294. {
  295.     int i;
  296.     *Rbuffptr++ = c;
  297.  
  298.     for(i = 0; i < Max_Readbuffer; i++)
  299.     {
  300.         *Rbuffptr++ = getachar();
  301.         switch(Ctype[Ch])
  302.         {
  303.         case SP:
  304.         case BR:
  305.         case QU:
  306.         case BA:
  307.             Rbuffptr --;
  308.             ungetachar();
  309.             break;
  310.         default:
  311.             continue;
  312.         }
  313.         break;
  314.     }
  315.     *Rbuffptr = '\0';
  316. }
  317.  
  318.  
  319. /******************************************************************
  320.             scan_number()
  321. *******************************************************************/
  322. static int scan_number(c)
  323. char c;
  324. {
  325.     int met_dot = 0;
  326.     int i;
  327.  
  328.     *Rbuffptr++ = c;
  329.     for(i = 0; i < MAXREALLENGTH; i++)
  330.     {
  331.         *Rbuffptr++ = getachar();
  332.         if(Ch == '.')
  333.             met_dot++;
  334.         if(!isdigit(Ch) && Ch != '.')
  335.         {
  336.             Rbuffptr --;
  337.             ungetachar();
  338.             break;
  339.         }
  340.     }
  341.  
  342.     *Rbuffptr = '\0';
  343.  
  344.     switch(met_dot)
  345.     {
  346.     case 0:
  347.         return(TOKEN_INT);
  348.     case 1:
  349.         return(TOKEN_REAL);
  350.     default:
  351.         return(SCAN_ERR);
  352.     }
  353. }
  354.  
  355. /******************************************************************
  356.             scan_string()
  357. Read a string and only store the characters between the quotes.
  358. To handle embeded quotes double them up.
  359. *******************************************************************/
  360. /* a bit crude ... */
  361. static void scan_string()
  362. {
  363.     int i, c;
  364.  
  365.     i = 0;
  366.     do{
  367.         c = getachar();
  368.         if(c == EOF)break;
  369.         if(c == STRING_QUOTE)
  370.         {
  371.             c = getachar();
  372.             if(c != '"')/* it really is the end of the string */
  373.             {
  374.                 ungetachar();
  375.                 break;/* dont store the quote */
  376.             }
  377.         }
  378.         *Rbuffptr++ = c;
  379.     }while(++i < Max_Readbuf